(function () {
  'use strict';

  angular
    .module('client')
    .factory('uploadService', uploadService);

  uploadService.$inject = ['$q', '$http', '$timeout', 'UPLOAD_URL'];
  function uploadService($q, $http, $timeout, UPLOAD_URL ) {
    var services = {
      installFile:installFile,
      askStatus: askStatus,
    };
    return services;

    function installFile(options, $eles) {
      var defer = $q.defer();
      var formdata = new FormData();

      $eles.$iBox.hide();
      $eles.$pBox.show();
      for(var name in options) {
        formdata.append(name, options[name]);
      }
      $http.post(UPLOAD_URL.link, formdata, {
        transformRequest: angular.identity,
        headers: {'Content-Type': undefined},
        uploadEventHandlers: {
          progress: function (e) {
            if (e.lengthComputable) {
              $eles.$progress.width(parseFloat(e.loaded / e.total * 90).toFixed(2) + "%");
              //console.log( "Recived" + e.loaded + " of " + e.total + " bytes, finished" + parseFloat(e.loaded / e.total * 100).toFixed(2) + "%");
            }
          }},
      })
        .then(function (data, header, config, status) {

          defer.resolve(data);
        }, function (err) {
          defer.reject(err);
        });
      return defer.promise;
    }

    function askStatus(opts, $eles) {
      var opt = {};

      $eles.$input.val('');
      if (opts.status !== 200) {
        console.error("file upload failed" );
        return;
      }
      opt.ticket = opts.data.ticket;
      sendAskRequest(opt, $eles);
    }

    function sendAskRequest(opt, $eles) {
      var $progress = $eles.$progress;
      var text = '';

      $http.post(UPLOAD_URL.check, opt).then(function (data, header, config, status) {
        data = data.data;
        switch (data.result) {
          case 'undefined':
            $timeout(function () {
              sendAskRequest(opt, $eles);
            }, 300);
            return;
          case 'ok':
            $progress.width('100%')
              .attr('status', 'finish');
            text = '安装成功';
            break;
          case 'download failed':
            $progress.width('100%')
              .attr('status', 'warn');
            text = '传输失败';
            break;
          case 'install failed':
            $progress.width('100%')
              .attr('status', 'warn');
            text = '安装失败';
            break;
          case 'device offline':
            $progress.width('100%')
              .attr('status', 'warn');
            text = '设备离线';
            break;
          default:
            break;
        }
        animation($eles, text);
      }, function (err) {
        $progress.width('100%')
          .attr('status', 'warn');
        text = '上传失败';
        animation($eles, text);
        console.error(err);
      });
    }

    function animation($eles, text) {
      var $progress = $eles.$progress;
      var $iBox = $eles.$iBox;
      var $pBox = $eles.$pBox;
      var $pBar = $eles.$pBar;
      var $text = $eles.$text;
      $.when(animate($pBar, 'hide', 1000))
        .done(function(){return setText($text, text)})
        .then(function(){return animate($text, 'show', 1200)})
        .then(function(){return animate($pBox, 'hide')})
        .done(function(){return animate($iBox, 'show')})
        .done(function(){return animate($text, 'hide')})
        .done(function(){return animate($pBar, 'show')})
        .done(function(){return setText($text, '')})
        .done(function(){return setSize($progress, 'width', '0')})
        .done(function(){return setStyle($progress, 'attr', 'status', '')});
    }

    function animate($ele, fn, time) {
      var defer = $.Deferred();
      if(time) {
        $ele[fn](function () {
          $timeout(function () {
            defer.resolve();
          }, time);
        });
      }
      else {
        $ele[fn](function () {
          defer.resolve();
        });
      }

      return defer.promise();

    }

    function setText($ele, text) {
      var defer = $.Deferred();
      $ele.html(text);
      defer.resolve();
      return defer.promise();
    }

    function setSize($ele, fn, param) {
      var defer = $.Deferred();
      $ele[fn](param);
      defer.resolve();
      return defer.promise();
    }

    function setStyle($ele, fn, param1, param2) {
      var defer = $.Deferred();
      $ele[fn](param1, param2);
      defer.resolve();
      return defer.promise();
    }

  }
})();

